#include "include.h"

static const char *TAG = "MQTT";

extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start");
extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end");
extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start");
extern const uint8_t client_key_pem_end[] asm("_binary_client_key_end");
extern const uint8_t server_cert_pem_start[] asm("_binary_ca_crt_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_ca_crt_end");
extern EventGroupHandle_t refresh_led_group;
/*
    mqtt发送消息队列
*/
xQueueHandle mqtt_send_data_queue;
/*
    mqtt事件队列
*/
xQueueHandle mqtt_evt_queue;

/**
 * 函数功能：处理mqtt收到的数据，并分发到指定的事件队列
 */
static esp_err_t handle_mqtt_data(esp_mqtt_event_handle_t event)
{
    char json_msg[256];

    ESP_LOGI(TAG, "topic -> %.*s", event->topic_len, event->topic);
    ESP_LOGI(TAG, "data -> %.*s", event->data_len, event->data);

    /*
        文本消息
    */
    if (strstr(event->topic, TENCENT_MQTTS_TOPIC_TEXT) != 0)
    {
        memset(json_msg, 0, sizeof(json_msg));
        strncpy(json_msg, event->data, event->data_len);
        /**
         * 存储到nvs下次开机执行
         */
        lonon_nvs_set_str(NVS_LED_EVENT, LED_EVENT_JSONG, json_msg);
        xEventGroupSetBits(refresh_led_group, REFRESH_LED);
    }

    /*
        led驱动消息
    */
    if (strstr(event->topic, TENCENT_MQTTS_TOPIC_LED) != 0)
    {
        memset(json_msg, 0, sizeof(json_msg));
        strncpy(json_msg, event->data, event->data_len);

        cJSON *json, *json0, *json1 *json2, *json3, *json4;

        if (cJSON_IsObject(json_msg))
        {
            json0 = cJSON_GetObjectItem(json, "led_0");
            if(json0)
            {

            }
            json1 = cJSON_GetObjectItem(json, "led_1");
            if(json1)
            {
                
            }
            json2 = cJSON_GetObjectItem(json, "led_2");
            if(json2)
            {
                
            }
            json3 = cJSON_GetObjectItem(json, "led_3");
            if(json3)
            {
                
            }
            json4 = cJSON_GetObjectItem(json, "led_4");
            if(json4)
            {
                
            }
        }
    }
    
    return ESP_OK;
}
/**
 * 函数功能发送设备影子信息
 */
esp_err_t send_shadow()
{
    char shadow_string[512];
    mqtt_send_queue_struct mqtt_send_queue = {0};
    /**
     * 生成影子数据
     */
    build_shadow_string(shadow_string, sizeof(shadow_string));
    memset(mqtt_send_queue.topic, '\0', sizeof(mqtt_send_queue.topic));
    memset(mqtt_send_queue.message, '\0', sizeof(mqtt_send_queue.message));
    if (strlen(TENCENT_MQTTS_SHADOW_TOPIC) > sizeof(mqtt_send_queue.topic))
    {
        ESP_LOGE(TAG, "xQueueSendFromISR send data to long!");
        return ESP_FAIL;
    }
    if (strlen(shadow_string) > sizeof(mqtt_send_queue.message))
    {
        ESP_LOGE(TAG, "xQueueSendFromISR send data to long!");
        return ESP_FAIL;
    }
    strcpy(mqtt_send_queue.topic, TENCENT_MQTTS_SHADOW_TOPIC);
    strcpy(mqtt_send_queue.message, shadow_string);
    mqtt_send_queue.qos = 0;
    /**
     * 发送影子数据
     */
    xQueueSend(mqtt_send_data_queue, &mqtt_send_queue, 0);
    return ESP_OK;
}
/**
 * 函数功能发送设备OTA信息
 */
esp_err_t send_ota_info()
{
    char shadow_string[512];
    mqtt_send_queue_struct mqtt_send_queue = {0};
    /**
     * 生成影子数据
     */
    build_ota_string(shadow_string, sizeof(shadow_string));
    memset(mqtt_send_queue.topic, '\0', sizeof(mqtt_send_queue.topic));
    memset(mqtt_send_queue.message, '\0', sizeof(mqtt_send_queue.message));
 
    strcpy(mqtt_send_queue.topic, TENCENT_MQTTS_OTA_REPORT_TOPIC);
    strcpy(mqtt_send_queue.message, shadow_string);
    mqtt_send_queue.qos = 0;
    /**
     * 发送影子数据
     */
    xQueueSend(mqtt_send_data_queue, &mqtt_send_queue, 0);
    return ESP_OK;
}
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch (event->event_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        /**
         * 发送队列信息，不等待后续执行
         */
        xQueueSend(mqtt_evt_queue, &event, 0);
        /**
         * 订阅TOPIC
         */
        msg_id = esp_mqtt_client_subscribe(client, TENCENT_MQTTS_TOPIC_TEXT, TENCENT_MQTTS_QOS_TEXT);
        ESP_LOGI(TAG, "sent subscribe successful, %s ,msg_id=%d", TENCENT_MQTTS_TOPIC_TEXT, msg_id);
        msg_id = esp_mqtt_client_subscribe(client, TENCENT_MQTTS_TOPIC_SPEAK, TENCENT_MQTTS_QOS_SPEAK);
        ESP_LOGI(TAG, "sent subscribe successful, %s ,msg_id=%d", TENCENT_MQTTS_TOPIC_SPEAK, msg_id);
        msg_id = esp_mqtt_client_subscribe(client, TENCENT_MQTTS_OTA_UPDATE_TOPIC, 1);
        ESP_LOGI(TAG, "sent subscribe successful, %s ,msg_id=%d", TENCENT_MQTTS_OTA_UPDATE_TOPIC, msg_id);
        /**
         * 发送设备影子信息
         */
        send_shadow();
        send_ota_info();
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        /**
         * 解析mqtt收到的数据
         */
        handle_mqtt_data(event);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
    return ESP_OK;
}

/*

    函数功能：启动mqtt服务器
    函数名称：lonon_mqtt_app_start

*/
void lonon_mqtt_app_start(void)
{
    mqtt_evt_queue = xQueueCreate(1, sizeof(esp_mqtt_event_handle_t));      /** 创建mqtt事件消息队列 */
    mqtt_send_data_queue = xQueueCreate(3, sizeof(mqtt_send_queue_struct)); /** mqtt发送消息队列 */
    xTaskCreate(mqtt_send_event_task, "mqtt_event", 4096, NULL, 5, NULL);   /** 创建mqtt事件任务 */

    const esp_mqtt_client_config_t mqtt_cfg = {
        .uri = TENCENT_MQTTS_URL_PART,
        .client_id = TENCENT_MQTTS_CLIENT_ID,
        .username = TENCENT_MQTTS_USER_NAME,
        .port = 8883,
        .event_handle = mqtt_event_handler_cb,
        .client_cert_pem = (const char *)client_cert_pem_start,
        .client_key_pem = (const char *)client_key_pem_start,
        .cert_pem = (const char *)server_cert_pem_start,
    };

    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_start(client);
}
/*

    函数功能：mqtt事件任务
    函数名字：mqtt_send_event_task

*/
void mqtt_send_event_task()
{
    int msg_id;
    mqtt_send_queue_struct mqtt_send_queue;
    esp_mqtt_event_handle_t event;

    memset(mqtt_send_queue.topic, '\0', sizeof(mqtt_send_queue.topic));
    memset(mqtt_send_queue.message, '\0', sizeof(mqtt_send_queue.message));

    ESP_LOGI(TAG, "hello mqtt_send_event_task!");
    /**
     * 等待首次获取client才进行往下执行
     * 这里等待mqtt成功连接后队列事件
     */
    xQueueReceive(mqtt_evt_queue, &event, portMAX_DELAY);
    esp_mqtt_client_handle_t client = event->client;
    while (1)
    {
        /**
         * 死等，等到有需要发送的数据就执行发送
         */
        if (xQueueReceive(mqtt_send_data_queue, &mqtt_send_queue, portMAX_DELAY))
        {
            ESP_LOGI(TAG, "topic:%s", mqtt_send_queue.topic);
            ESP_LOGI(TAG, "message:%s", mqtt_send_queue.message);
            ESP_LOGI(TAG, "qos:%d", mqtt_send_queue.qos);
            msg_id = esp_mqtt_client_publish(client, mqtt_send_queue.topic, mqtt_send_queue.message, 0, mqtt_send_queue.qos, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        }
    }
}
